﻿namespace DCHealthCheck.MvcWeb.Classes {

    #region Usings
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using System.Web.Caching;
    using System.Web.Security; 
    #endregion

    /// <summary>
    /// Provides role information for an ASP.NET application from Windows group membership.
    /// </summary>
    /// <remarks>
    /// Overriden to add proper caching of roles.
    /// </remarks>
    internal class WindowsTokenCachingRoleProvider : WindowsTokenRoleProvider {

        private readonly int RoleCacheTimeoutMinutes = 5;

        /// <summary>
        /// Required for provider model.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public WindowsTokenCachingRoleProvider() {
            if (ConfigurationManager.AppSettings["RoleCacheTimeoutMinutes"] != null) {
                int.TryParse(ConfigurationManager.AppSettings["RoleCacheTimeoutMinutes"], out this.RoleCacheTimeoutMinutes);
            }

            this.ApplicationName = Global.ApplicationName;
        }

        /// <summary>
        /// Gets a list of the Windows groups that a user is in.
        /// </summary>
        /// <param name="username">
        /// The user to return the list of Windows groups for in the form DOMAIN\username.
        /// </param>
        /// <returns>
        /// A string array containing the names of all the Windows groups of which the specified user is a member
        /// </returns>
        public override string[] GetRolesForUser(string username) {

            // List of Windows groups for the given user.
            string[] roles;

            if ((HttpContext.Current != null) && (HttpContext.Current.Cache != null)) {
                // Create a key for the requested user.
                string cacheKey = username + ":" + base.ApplicationName;

                // Get the cache for the current HTTP request.
                Cache cache = HttpContext.Current.Cache;

                // Attempt to fetch the list of roles from the cache.
                roles = cache[cacheKey] as string[];

                // If the list is not in the cache we will need to request it.
                if (null == roles) {
                    // Allow the base implementation to load the list of roles.
                    roles = base.GetRolesForUser(username);
                    // Add the resulting list to the cache.
                    cache.Insert(cacheKey, roles, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(this.RoleCacheTimeoutMinutes));
                }
            }
            else {
                roles = base.GetRolesForUser(username);
            }

            // Return the resulting list of roles.
            return roles;
        }
    }
}